package com.chart.web.controller.chart;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.CannedAccessControlList;
import com.chart.common.core.domain.AjaxResult; // Import your unified response class
import com.chart.common.utils.ByteArrayMultipartFile;
import jdk.nashorn.internal.runtime.regexp.joni.Config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.*;

/**
 * 阿里云OSS存储用于颜色识别
 */
@Slf4j
@RestController
@RequestMapping("/oss")
public class OSSController {

    @Value("${aliyun.oss.endpoint}")
    private String endpoint;

    @Value("${aliyun.oss.accessKeyId}")
    private String accessKeyId;

    @Value("${aliyun.oss.accessKeySecret}")
    private String accessKeySecret;

    @Value("${aliyun.oss.bucketName}")
    private String bucketName;


    /**
     * 阿里云OSS
     * @param file
     * @return
     */
    @PostMapping("/upload")
    public AjaxResult uploadFile(@RequestParam("file") MultipartFile file) {
        if (ObjectUtils.isEmpty(file)) {
            log.warn("上传文件为空");
            return AjaxResult.warn("上传文件为空");
        }

        // 文件大小限制，超过1MB则直接返回错误
        long maxFileSize = 1 * 1024 * 1024; // 1MB
        if (file.getSize() > maxFileSize) {
            log.warn("文件大小超过限制，文件大小: {} bytes", file.getSize());
            return new AjaxResult(602, "您上传的图片超过1M，请重新上传！");
        }

        // 定义压缩文件的大小阈值，例如超过300KB时进行压缩
        final long compressionThreshold = 300 * 1024; // 300KB
        MultipartFile compressedFile = file; // 默认使用原始文件

        try {
            // 如果文件大于阈值，进行压缩
            if (file.getSize() > compressionThreshold) {
                // 将 MultipartFile 转换为 BufferedImage
                BufferedImage image = ImageIO.read(file.getInputStream());

                // 压缩图片，降低质量
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                float quality = 0.5f; // 定义压缩质量（0-1之间，数值越低压缩越高）

                // 获取 JPEG 写入器
                ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next();
                ImageWriteParam param = writer.getDefaultWriteParam();

                // 设置压缩质量
                param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
                param.setCompressionQuality(quality);

                // 创建 ImageOutputStream
                try (ImageOutputStream ios = ImageIO.createImageOutputStream(baos)) {
                    writer.setOutput(ios);
                    writer.write(null, new IIOImage(image, null, null), param);
                    baos.flush();
                }

                // 转换为 InputStream 以便上传
                byte[] compressedBytes = baos.toByteArray();
                InputStream compressedInputStream = new ByteArrayInputStream(compressedBytes);

                // 创建压缩后的 MultipartFile
                compressedFile = new ByteArrayMultipartFile(compressedBytes, file.getName(),
                        file.getOriginalFilename(), file.getContentType());
                log.info("图片已压缩，原始大小: {} bytes, 压缩后大小: {} bytes", file.getSize(), compressedFile.getSize());
            }
        } catch (Exception e) {
            log.error("图片压缩失败", e);
            return AjaxResult.error("图片压缩失败");
        }

        // 校验文件类型（只允许图片格式）
        String contentType = compressedFile.getContentType();
        if (contentType == null || !contentType.startsWith("image/")) {
            log.warn("不支持的文件类型: {}", contentType);
            return AjaxResult.warn("文件类型不支持，请上传jpg或png格式图片文件！");
        }

        // 创建 OSS 客户端实例
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        AjaxResult result;
        String uniqueFileName = null;

        try {
            // 生成唯一的文件名（使用时间戳 + 文件名）
            uniqueFileName = "uploads/" + System.currentTimeMillis() + "_" + compressedFile.getOriginalFilename();

            // 上传文件到 OSS
            ossClient.putObject(bucketName, uniqueFileName, compressedFile.getInputStream());

            // 设置文件为公共读
            ossClient.setObjectAcl(bucketName, uniqueFileName, CannedAccessControlList.PublicRead);

            // 构造图片 URL
            String imageUrl = "https://" + bucketName + "." + endpoint + "/" + uniqueFileName;

            // 获取颜色统计（假设你已经有这个方法）
            List<String> topColors = getTopImageColors(ossClient, bucketName, uniqueFileName);

            // 返回图片 URL 和颜色统计信息
            Map<String, Object> data = new HashMap<>();
            data.put("imageUrl", imageUrl);
            data.put("colors", topColors);
            log.info("上传文件成功");
            result = AjaxResult.success("操作成功", data);
        } catch (Exception e) {
            e.printStackTrace();
            log.warn("文件上传失败: " + e.getMessage());
            result = AjaxResult.error("文件上传失败: " + e.getMessage());
        } finally {
            // 删除已上传的文件
            if (uniqueFileName != null) {
                ossClient.deleteObject(bucketName, uniqueFileName);
            }
            ossClient.shutdown();
        }
        return result;
    }


    private List<String> getTopImageColors(OSS ossClient, String bucketName, String objectName) {
        Map<String, Integer> colorCountMap = new HashMap<>();

        try {
            // 从 OSS 获取图片输入流
            InputStream inputStream = ossClient.getObject(bucketName, objectName).getObjectContent();
            BufferedImage image = ImageIO.read(inputStream);

            // 遍历每个像素，统计颜色
            for (int x = 0; x < image.getWidth(); x++) {
                for (int y = 0; y < image.getHeight(); y++) {
                    int pixel = image.getRGB(x, y);
                    Color color = new Color(pixel, true);  // 使用透明度

                    // 转换为颜色的字符串表示（格式: R,G,B）
                    String colorKey = String.format("%d,%d,%d", color.getRed(), color.getGreen(), color.getBlue());

                    // 统计颜色的出现次数
                    colorCountMap.put(colorKey, colorCountMap.getOrDefault(colorKey, 0) + 1);
                }
            }

            inputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 合并相似颜色
        Map<String, Integer> mergedColors = mergeSimilarColors(colorCountMap, 50); // 阈值设为 50

        // 根据出现次数排序并获取前6种颜色
        List<Map.Entry<String, Integer>> sortedColors = new ArrayList<>(mergedColors.entrySet());
        sortedColors.sort((a, b) -> b.getValue().compareTo(a.getValue()));

        List<String> topColors = new ArrayList<>();
        for (int i = 0; i < Math.min(6, sortedColors.size()); i++) {
            String[] rgb = sortedColors.get(i).getKey().split(",");
            String hexColor = String.format("#%02x%02x%02x",
                    Integer.parseInt(rgb[0]),
                    Integer.parseInt(rgb[1]),
                    Integer.parseInt(rgb[2]));
            topColors.add(hexColor);  // 添加十六进制颜色
        }

        return topColors;
    }

    // 合并相似颜色的方法
    private Map<String, Integer> mergeSimilarColors(Map<String, Integer> colorMap, int threshold) {
        Map<String, Integer> mergedMap = new HashMap<>();

        for (String colorKey : colorMap.keySet()) {
            Color color = new Color(
                    Integer.valueOf(colorKey.split(",")[0]),
                    Integer.valueOf(colorKey.split(",")[1]),
                    Integer.valueOf(colorKey.split(",")[2])
            );

            boolean foundSimilar = false;

            for (String mergedKey : mergedMap.keySet()) {
                Color mergedColor = new Color(
                        Integer.valueOf(mergedKey.split(",")[0]),
                        Integer.valueOf(mergedKey.split(",")[1]),
                        Integer.valueOf(mergedKey.split(",")[2])
                );

                // 计算欧几里得距离
                double distance = Math.sqrt(Math.pow(color.getRed() - mergedColor.getRed(), 2)
                        + Math.pow(color.getGreen() - mergedColor.getGreen(), 2)
                        + Math.pow(color.getBlue() - mergedColor.getBlue(), 2));

                if (distance < threshold) {
                    mergedMap.put(mergedKey, mergedMap.get(mergedKey) + colorMap.get(colorKey));
                    foundSimilar = true;
                    break;
                }
            }

            if (!foundSimilar) {
                mergedMap.put(colorKey, colorMap.get(colorKey));
            }
        }

        return mergedMap;
    }
}
